using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

using UIKit;

using Outcoder.Services.DialogService;

namespace Outcoder.Services.Implementation
{
	public partial class DialogService : DialogServiceBase
	{
		public override Task<int?> ShowDialogAsync(
			object body, IEnumerable<object> buttons, 
			string caption = null, 
			int defaultAcceptButtonIndex = -1,
			object expandableDetails = null,
			DialogController dialogController = null)
		{
			int clickedButtonIndex = -1;

			string[] buttonLabelArray;
			string cancelButtonLabel = null;

			if (buttons != null)
			{
				object[] tempArray = buttons.ToArray();

				if (tempArray.Length > 0)
				{
					cancelButtonLabel = tempArray[0] + string.Empty;
					buttonLabelArray = new string[tempArray.Length - 1];
					Array.Copy(tempArray, 1, buttonLabelArray, 0, tempArray.Length - 1);
				}
				else
				{
					List<string> temp = new List<string>();
					foreach (var o in tempArray)
					{
						string arrayValue = o != null ? o.ToString() : string.Empty;
						temp.Add(arrayValue);
					}
					buttonLabelArray = temp.ToArray();
				}
			}
			else
			{
				buttonLabelArray = new string[0];
			}

			if (cancelButtonLabel == null)
			{
				cancelButtonLabel = DefaultOkaySymbol;
			}

			string bodyText = body != null ? body.ToString() : string.Empty;
			
			TaskCompletionSource<int?> source = new TaskCompletionSource<int?>();

			UIAlertView alert;

			if (caption == null)
			{
				alert = new UIAlertView();
				alert.Message = bodyText;
				int cancelButtonIndex = 0;

				foreach (var buttonLabel in buttonLabelArray)
				{
					alert.AddButton(buttonLabel);
					cancelButtonIndex++;
				}

				alert.AddButton(cancelButtonLabel);
				alert.CancelButtonIndex = cancelButtonIndex;
			}
			else
			{
				alert = new UIAlertView(caption, bodyText, null, cancelButtonLabel, buttonLabelArray);
			}

			alert.Clicked += (sender, buttonArgs) =>
				{
					clickedButtonIndex = (int)buttonArgs.ButtonIndex;
					source.SetResult(clickedButtonIndex);
				};

			alert.Canceled += delegate { source.SetResult(null); };

			try
			{
				alert.Show();
			}
			catch (Exception ex)
			{
				source.SetException(ex);
			}

			return source.Task;
		}

		public string DefaultOkaySymbol = '\u2714' + string.Empty;
		public string DefaultCancelSymbol = '\u2718' + string.Empty;

		public async override Task<DialogResult> ShowDialogAsync(
			object content, 
			string caption, 
			DialogButton dialogButton, 
			DialogImage dialogImage = DialogImage.None,
			DialogImportance importanceThreshold = DialogImportance.High, 
			object details = null,
			DialogController dialogController = null)
		{
			List<string> buttons = new List<string>();

			if (dialogButton == DialogButton.OK)
			{
				buttons.Add(DefaultOkaySymbol);
			}
			else if (dialogButton == DialogButton.OKCancel || dialogButton == DialogButton.YesNo
					 || dialogButton == DialogButton.YesNoCancel)
			{
				buttons.Add(DefaultOkaySymbol);
				buttons.Add(DefaultCancelSymbol);
			}

			var selectedIndex = await this.ShowDialogAsync(content, buttons, caption, 0, dialogController: dialogController);

			if (selectedIndex == null || selectedIndex < 0)
			{
				return DialogResult.Cancel;
			}

			if (selectedIndex == 0)
			{
				return dialogButton == DialogButton.OKCancel ? DialogResult.OK : DialogResult.Yes;
			}

			if (selectedIndex == 1)
			{
				return DialogResult.Cancel;
			}

			throw new IndexOutOfRangeException("Index returned from dialog is out of range. " + selectedIndex);
		}

		public async override Task<QuestionResponse<TResponse>> AskQuestionAsync<TResponse>(IQuestion<TResponse> question)
		{
			throw new System.NotImplementedException();
		}
	}
}